﻿using System;
using System.Text;
using System.ServiceModel;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using DXTools.Core;
using DXTools.Core.CrmSdk;
using DXTools.Core.Model;
using System.Collections.ObjectModel;
using DXTools.Core.Enum;
using System.IO;


namespace DXTools.UI.Core.DataProviders
{

    public class CRMDataProvider : ICRMDataProvider
    {
        Uri _server;

        public CRMDataProvider()
        {
            _server = new Uri(DXTools.Core.ClientScript.GetServerUrl());
        }

        public void RetrieveWebResourceList(WebResourceType webResourceType,AsyncCallback asyncCallback)
        {
            try
            {
                DXTools.Core.CrmSdk.IOrganizationService service = DXTools.Core.WCFHelper.GetConnection(_server);
               
                //OrganizationRequest request = new OrganizationRequest();

                QueryExpression query = new QueryExpression();
                query.ColumnSet = new ColumnSet();
                query.ColumnSet.Columns = new ObservableCollection<string>(
                    new string[] { "webresourceid", "name", "displayname" });
                
                query.Criteria = new FilterExpression
                {
                    FilterOperator = LogicalOperator.And,
                    Conditions = {
                        new ConditionExpression
                        {
                            AttributeName = "webresourcetype",
                            Operator = ConditionOperator.Equal,
                            Values = { (int)webResourceType }
                        }
                        ,
                        new ConditionExpression
                        {
                            AttributeName = "ishidden",
                            Operator = ConditionOperator.Equal,
                            Values = { "false" }
                        }
                    }
                };
                
                query.EntityName = "webresource";

                service.BeginRetrieveMultiple(query, asyncCallback, service);

            }
            catch (FaultException<OrganizationServiceFault> ex)
            {
                throw ex;
            }
        }

        public void RetrieveWebResource(String WebResourceId, AsyncCallback asyncCallback)
        {
            try
            {
            DXTools.Core.CrmSdk.IOrganizationService service = DXTools.Core.WCFHelper.GetConnection(_server);

            ColumnSet cols = new ColumnSet();
            //cols.AllColumns = true;

            cols.Columns = new ObservableCollection<string>(new string[] { "webresourceid", "name" , "description" , "content", "displayname" });


            service.BeginRetrieve("webresource", new Guid(WebResourceId), cols, asyncCallback, service);

            }
            catch (FaultException<OrganizationServiceFault> ex)
            {
                throw ex;
            }
        }

        public void  UpdateWebResource(String WebResourceId, String Content, AsyncCallback asyncCallback)
        {
            try
            {
                DXTools.Core.CrmSdk.IOrganizationService service = DXTools.Core.WCFHelper.GetConnection(_server);

                String data = Convert.ToBase64String(Encoding.UTF8.GetBytes(Content));

                Entity webResource = new Entity() { LogicalName = "webresource" };
                webResource.Id = new Guid(WebResourceId);
                webResource.Attributes = new AttributeCollection();
                webResource.Attributes.Add(new DXTools.Core.CrmSdk.KeyValuePair<string,object>("content", data));

                service.BeginUpdate(webResource, asyncCallback, service);

            }
            catch (FaultException<OrganizationServiceFault> ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// SilverLight Async version
        /// </summary>
        /// <param name="WebResourceId"></param>
        /// <param name="asyncCallback"></param>
        public void PublishWebResource(String WebResourceId, AsyncCallback asyncCallback)
       {
           DXTools.Core.CrmSdk.IOrganizationService service = DXTools.Core.WCFHelper.GetConnection(_server);


           OrganizationRequest publishRequest = new OrganizationRequest();
           publishRequest.RequestName = "PublishXml";

           string publishXml = "<importexportxml><webresources><webresource>" + WebResourceId + "</webresource></webresources></importexportxml>";

           publishRequest.Parameters = new ParameterCollection();
           DXTools.Core.CrmSdk.KeyValuePair<string, object> myParam = new DXTools.Core.CrmSdk.KeyValuePair<string, object>();
           myParam.Key = "ParameterXml";
           myParam.Value = publishXml;

           publishRequest.Parameters.Add(myParam);


           service.BeginExecute(publishRequest, asyncCallback, service);

       }



        #region Sitemap Methods

        /// <summary>
        /// Retrieve the current sitemap
        /// </summary>
        /// <param name="asyncCallback"></param>
        public void RetrieveSitemap(AsyncCallback asyncCallback)
        {
           
            DXTools.Core.CrmSdk.IOrganizationService service = DXTools.Core.WCFHelper.GetConnection(_server);
            QueryExpression query = new QueryExpression();
            query.EntityName = "sitemap";
            query.NoLock = true;
            
            ColumnSet cols = new ColumnSet();
            cols.AllColumns = true;
            query.ColumnSet = cols;

            service.BeginRetrieveMultiple(query, asyncCallback, service);

        }

        /// <summary>
        /// Publish Sitemap
        /// </summary>
        /// <param name="asyncCallback"></param>
        public void PublishSitemap(AsyncCallback asyncCallback)
        {

            DXTools.Core.CrmSdk.IOrganizationService service = DXTools.Core.WCFHelper.GetConnection(_server);


            OrganizationRequest publishRequest = new OrganizationRequest();
            publishRequest.RequestName = "PublishXml";

            string publishXml = "<importexportxml><sitemaps><sitemap></sitemap></sitemaps></importexportxml>";

            publishRequest.Parameters = new ParameterCollection();
            DXTools.Core.CrmSdk.KeyValuePair<string, object> myParam = new DXTools.Core.CrmSdk.KeyValuePair<string, object>();
            myParam.Key = "ParameterXml";
            myParam.Value = publishXml;

            publishRequest.Parameters.Add(myParam);


            service.BeginExecute(publishRequest, asyncCallback, service);
        }

    

        #endregion 

        #region Solution Methods


        public void ImportSolution(Tool tool, Guid importJobId, string base64SolutionFile, AsyncCallback asyncCallback)
        {
            Entity installSolutionCommand = new Entity();
            installSolutionCommand.LogicalName = "dxtools_installsolutioncommand";
            installSolutionCommand["dxtools_name"] = tool.Name;
            installSolutionCommand["dxtools_displayname"] = tool.DisplayName;
            installSolutionCommand["dxtools_ref"] = tool.Ref;
            installSolutionCommand["dxtools_modulename"] = tool.ModuleName;
            installSolutionCommand["dxtools_moduletype"] = tool.ModuleType;
            installSolutionCommand["dxtools_version"] = tool.Version;
            installSolutionCommand["dxtools_importjobid"] = importJobId.ToString();


            AsyncCallback asyncCallbackCreateInstallCommand = (resultImport =>
            {
                IOrganizationService serviceFromCallback = (IOrganizationService)resultImport.AsyncState;
                Guid installSolutionCommandId = serviceFromCallback.EndCreate(resultImport);

                CreateAttachment(installSolutionCommandId, "dxtools_installsolutioncommand", base64SolutionFile, asyncCallback);
            });
            
            IOrganizationService service = WCFHelper.GetConnection(_server);
            service.BeginCreate(installSolutionCommand, asyncCallbackCreateInstallCommand, service);
        }

        public void CreateAttachment(Guid objectID, string recordType, string base64documentBody, AsyncCallback asyncCallback)
        {
            Entity attachment = new Entity();
            attachment.LogicalName = "annotation";
            attachment["subject"] = "Install Solution Command";
            attachment["objectid"] = new EntityReference() { LogicalName = recordType, Id = objectID };
            attachment["objecttypecode"] = recordType;
            attachment["mimetype"] = "text/plain";
            attachment["documentbody"] = base64documentBody;

            IOrganizationService service = WCFHelper.GetConnection(_server);
            service.BeginCreate(attachment, asyncCallback, service);

        }

        /// <summary>
        /// Provides detail on the solution process result
        /// </summary>
        /// <param name="ImportJobId"></param>
        /// <param name="asyncCallback"></param>
        public void RetrieveImportJob(Guid ImportJobId, AsyncCallback asyncCallback)
        {
            IOrganizationService service = WCFHelper.GetConnection(_server);
            ColumnSet columns = new ColumnSet()
            {
                Columns = new ObservableCollection<string>(
                    new string[] { "data", "solutionname" })
            };
            service.BeginRetrieve("importjob", ImportJobId, columns, asyncCallback, service);

        }

        /// <summary>
        /// Retrieves the DXTools solutions in the system
        /// </summary>
        /// <param name="asyncCallback"></param>
        public void RetrieveSolutionList(AsyncCallback asyncCallback)
        {
            try
            {
                DXTools.Core.CrmSdk.IOrganizationService service = DXTools.Core.WCFHelper.GetConnection(_server);

                OrganizationRequest request = new OrganizationRequest();

                QueryExpression query = new QueryExpression();
                query.ColumnSet = new ColumnSet();
                query.ColumnSet.Columns = new ObservableCollection<string>(
                    new string[] { "solutionid", "uniquename", "friendlyname", "version" });

                query.Criteria = new FilterExpression
                {
                    FilterOperator = LogicalOperator.And,
                    Conditions = {
                        new ConditionExpression
                        {
                            AttributeName = "uniquename",
                            Operator = ConditionOperator.BeginsWith,
                            Values = { (string)"XRMTools" }
                        }
                    }
                        
                };

                query.EntityName = "solution";

                service.BeginRetrieveMultiple(query, asyncCallback, service);

            }
            catch (FaultException<OrganizationServiceFault> ex)
            {
                throw ex;
            }
        }
        ///// <summary>
        ///// Imports a solution file and returns the ImportJobId so that you can monitor the import's success
        ///// </summary>
        ///// <param name="SolutionFile">Base 64 string</param>
        ///// <returns></returns>
        //public Guid ImportSolution(string SolutionFile, AsyncCallback asyncCallback)
        //{
        //    Guid importJobId = Guid.NewGuid();
        //    // Monitor import success
        //    byte[] fileBytes = Convert.FromBase64String(SolutionFile);
        //    //System.Text.UnicodeEncoding encoding = new System.Text.UnicodeEncoding();
        //    //Byte[] fileBytes = encoding.GetBytes(SolutionFile);

        //    OrganizationRequest request = new OrganizationRequest();
        //    request.RequestName = "ImportSolution";

        //    request["CustomizationFile"] = fileBytes;
        //    //request["CustomizationFile"] =  SolutionFile;
        //    request["ImportJobId"] = importJobId;


        //    IOrganizationService service = WCFHelper.GetConnection(_server);

        //    service.BeginExecute(request, asyncCallback, service);

        //    return importJobId;

        //}
        #endregion

        #region Common Methods

        public void UpdateEntity(Entity entity, AsyncCallback asyncCallback)
        {
            DXTools.Core.CrmSdk.IOrganizationService service = DXTools.Core.WCFHelper.GetConnection(_server);

            service.BeginUpdate(entity, asyncCallback, service);
        }
        #endregion

       
        

    }
}
